package httpserver

import (
	"context"
	"fmt"
	"gitee.com/sansaniot/ssiot-core/config"
	"gitee.com/sansaniot/ssiot-core/facade/env"
	"gitee.com/sansaniot/ssiot-core/facade/httpserver/handler"
	"gitee.com/sansaniot/ssiot-core/facade/runtime"
	"gitee.com/sansaniot/ssiot-core/httpmvc/api"
	"gitee.com/sansaniot/ssiot-core/httpmvc/jwtauth"
	"gitee.com/sansaniot/ssiot-core/httpmvc/middleware"
	"gitee.com/sansaniot/ssiot-core/utils"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

var middlewareFunctions = make([]func(c *gin.Context), 0)

func RegisterMiddlewareFunction(f func(c *gin.Context)) {
	middlewareFunctions = append(middlewareFunctions, f)
}

func Run(cb ...func()) error {
	srv := &http.Server{
		Addr:    fmt.Sprintf("%s:%d", config.HttpConfig.Host, config.HttpConfig.Port),
		Handler: runtime.Runtime.GetEngine(),
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	go func() {
		// 服务连接
		if config.SslConfig.Enable {
			if err := srv.ListenAndServeTLS(config.SslConfig.Pem, config.SslConfig.KeyStr); err != nil && err != http.ErrServerClosed {
				log.Fatal("listen: ", err)
			}
		} else {
			if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
				log.Fatal("listen: ", err)
			}
		}
	}()

	fmt.Println(utils.Green(fmt.Sprintf("api server running at %s:%d", config.HttpConfig.Host, config.HttpConfig.Port)))
	fmt.Printf("%s enter Control + c shutdown Server \r\n", utils.GetCurrentTimeStr())

	// 等待中断信号以优雅地关闭服务器（设置 5 秒的超时时间）
	quit := make(chan os.Signal)
	signal.Notify(quit, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
	<-quit

	if len(cb) > 0 {
		cb[0]()
	}
	fmt.Printf("%s shutdown server ... \r\n", utils.GetCurrentTimeStr())

	if err := srv.Shutdown(ctx); err != nil {
		log.Printf("server shutdown. %s \r\n", err)
	}
	log.Println("server exiting")

	return nil
}

func InitEngine(configFile string) {
	// 加载系统配置
	env.SetupConfig(configFile, false)

	var r *gin.Engine

	if env.DefaultConfig.Http.Mode == "" {
		gin.SetMode(gin.ReleaseMode)
	} else {
		gin.SetMode(env.DefaultConfig.Http.Mode)
	}

	h := runtime.Runtime.GetEngine()

	if h == nil {
		h = gin.New()
		runtime.Runtime.SetEngine(h)
	}

	switch h.(type) {
	case *gin.Engine:
		r = h.(*gin.Engine)
	default:
		log.Fatal("not support other engine")
		os.Exit(-1)
	}

	//注册tls中间件，只能放在注册路由之前
	if config.SslConfig.Enable {
		r.Use(handler.TlsHandler())
	}

	// 在gin的上下文中使用db
	r.Use(middleware.WithContextDb)
	// 在gin的上下文中使用log
	r.Use(api.SetRequestLogger)

	//自定义中间件，只能放在注册路由之前
	for _, f := range middlewareFunctions {
		r.Use(f)
	}
}

func InitRouters(routers []func(*gin.RouterGroup)) {
	h := runtime.Runtime.GetEngine()
	// 不需要认证的路由
	runRouter(h.(*gin.Engine), routers)
}

func InitAuthRouters(routers []func(v1 *gin.RouterGroup, authMiddleware *jwtauth.GinJWTMiddleware), authMiddleware *jwtauth.GinJWTMiddleware) {
	h := runtime.Runtime.GetEngine()
	//需要认证组件的路由
	runAuthRouter(h.(*gin.Engine), authMiddleware, routers)
}
